package com.hysf.service.impl;

import com.hysf.dao.AccountDao;
import com.hysf.dao.OpRecordDao;
import com.hysf.pojo.Account;
import com.hysf.pojo.OpRecord;
import com.hysf.pojo.OpType;
import com.hysf.service.BankBiz;
import com.hysf.utils.DateFormat;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;


@Service
@RequiredArgsConstructor
@Slf4j
@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
public class BankBizImpl implements BankBiz {
	
	private final AccountDao accountDao;
	private final OpRecordDao opRecordDao;
	
	@Override
	public void transfer(Integer srcaccountid, Integer taraccountid, double money) {
		Account src = accountDao.findById(srcaccountid);
		Account tar = accountDao.findById(taraccountid);
		if (src == null || tar == null) {
			log.error("账户不存在");
			throw new RuntimeException("账户不存在");
		}
		if (src.getBalance().doubleValue() <= money) {
			log.error("余额不足");
			throw new RuntimeException("余额不足");
		}
		src.setBalance(src.getBalance().doubleValue() - money);
		tar.setBalance(tar.getBalance().doubleValue() + money);
		accountDao.update(srcaccountid, src.getBalance().doubleValue());
		accountDao.update(taraccountid, tar.getBalance().doubleValue());
		log.info(srcaccountid+"在 "+ DateFormat.format(new Date()) +" 向"+taraccountid+"转"+money+"元");
		OpRecord opRecord = new OpRecord();
		opRecord.setAccountid(srcaccountid);
		opRecord.setOpmoney(-money);
		opRecord.setOptime(DateFormat.format(new Date()));
		opRecord.setOptype(OpType.TRANSFER);
		opRecordDao.insertOpRecord(opRecord);
		OpRecord opRecord2 = new OpRecord();
		opRecord2.setAccountid(taraccountid);
		opRecord2.setOpmoney(money);
		opRecord2.setOptime(DateFormat.format(new Date()));
		opRecord2.setOptype(OpType.TRANSFER);
		opRecordDao.insertOpRecord(opRecord2);
	}
	
	@Override
	public Account openAccount(double money) {
		int accountid = accountDao.insert(money);
		log.info(accountid+"在 "+ DateFormat.format(new Date()) +" 开户!");
		OpRecord opRecord = new OpRecord();
		opRecord.setAccountid(accountid);
		opRecord.setOpmoney(money);
		opRecord.setOptime(DateFormat.format(new Date()));
		opRecord.setOptype(OpType.DEPOSITE);
		opRecordDao.insertOpRecord(opRecord);
		return accountDao.findById(accountid);
	}
	
	@Override
	public Account deposite(Integer accountid, double money) {
		Account account = accountDao.findById(accountid);
		if (account == null) {
			log.error("账户不存在");
			throw new RuntimeException("账户不存在");
		}
		account.setBalance(account.getBalance().doubleValue() + money);
		accountDao.update(accountid, account.getBalance().doubleValue());
		log.info(accountid+"在 "+ DateFormat.format(new Date()) +" 存款"+money+"元");
		OpRecord opRecord = new OpRecord();
		opRecord.setAccountid(accountid);
		opRecord.setOpmoney(money);
		opRecord.setOptime(DateFormat.format(new Date()));
		opRecord.setOptype(OpType.DEPOSITE);
		opRecordDao.insertOpRecord(opRecord);
		return accountDao.findById(accountid);
	}
	
	@Override
	public Account withdraw(Integer accountid, double money) {
		Account account = accountDao.findById(accountid);
		if (account == null) {
			log.error("账户不存在");
			throw new RuntimeException("账户不存在");
		}
		if (account.getBalance().doubleValue() <= money) {
			log.error("余额不足");
			throw new RuntimeException("余额不足");
		}
		account.setBalance(account.getBalance().doubleValue() - money);
		accountDao.update(accountid, account.getBalance().doubleValue());
		log.info(accountid+"在 "+ DateFormat.format(new Date()) +" 取款"+money+"元");
		OpRecord opRecord = new OpRecord();
		opRecord.setAccountid(accountid);
		opRecord.setOpmoney(money);
		opRecord.setOptime(DateFormat.format(new Date()));
		opRecord.setOptype(OpType.WITHDRAW);
		opRecordDao.insertOpRecord(opRecord);
		return accountDao.findById(accountid);
	}
	
	@Override
	@Transactional(readOnly = true)
	public Account findAccount(Integer accountid) {
		return accountDao.findById(accountid);
	}
}
